<?php
/**
 * 整体妆容列表
 *
 * Author: lyun
 * Date: 2018/3/27
 * Created by Panxsoft.
 */


namespace App\Http\Controllers\App;

use App\Http\Controllers\ApiController;
use App\Models\Customer\Asset;
use App\Models\Customer\Customer;
use App\Models\Panx\Product;
use App\Models\Store\Pack;
use App\Models\Store\PackCategory;
use App\Services\Repositories\Pack\PackRepository;
use App\Services\Utils\Guard;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\HasMany;


class PackController extends ApiController
{
    const ROUTE = [
        'list' => 'api.app.v2-3-1-10.pack.list'
    ];

    /**
     * 按类别分组返回整体妆容
     * @test
     *
     * @return array|\Illuminate\Http\Response
     */
    public function list()
    {
        $customer = Guard::deviceAccount()->customer;

        // 获取已分类的整妆
        /** @var Collection $pack_categories */
        $pack_categories = (new PackCategory)
            ->where('customer_id', $customer->id)
            ->with([
                'packs' => $this->queryPackOnShelf(),
                'packs.assets',
            ])
            ->get();

        $pack_categories = $this->filterEmptyPackCategory($pack_categories);

        // 处理产品数据格式
        $this->transformPackCategoryProducts($pack_categories);

        // 追加未分类的其他整妆
        $this->appendOtherPackCategory($pack_categories, $customer);

        return $this->response(compact('pack_categories'));
    }

    /**
     * @deprecated - v2.3.10 增加整妆分类访问 list() 方法
     * @see PackController::list()
     *
     * Pad 整体妆容列表
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $store = Guard::deviceAccount()->store;
        $customer = Guard::deviceAccount()->customer;

        /** @var Collection $packs */
        $packs = (new Pack)
            ->where('store_id', $store->id)
            ->orWhere([
                ['store_id', Pack::STORE_ID_CUSTOMER],
                ['customer_id', $customer->id],
            ])
            ->with(['assets.firstProduct.thumbImage', 'assets.assetPivotProducts.thumbImage'])
            ->get();
        $this->transformPackProducts($packs);

        return $this->response(compact('packs'));
    }


    /**
     * @deprecated - v2.3.10 后已不再使用
     *
     * @param Collection $packs
     */
    private function transformPackProducts(Collection $packs)
    {
        // pack <= pack_pivot_asset => assets <= asset_pivot_product => products
        $packs->each(function (Pack $pack) {
            $pack->assets->each(function (Asset $asset) {
                $prod = $asset->firstProduct;
                if ($prod) {
                    $asset->product = $prod;
                    $prod->append(['thumb_url']);
                    $prod->addHidden(['thumbImage']);
                } else {
                    $asset->product = null;
                }
                $asset->addHidden(['firstProduct']);

                // asset_pivot_product
                $asset->pivot_products = $this->transformPivotProducts($asset->assetPivotProducts);

//                $asset->addHidden(['pivot']);
//                $asset->addHidden(['pivot_products']);
            });
        });
    }

    /**
     *
     * @param Collection|Product[] $pivotProducts
     * @return $this|Collection
     */
    private function transformPivotProducts(Collection $pivotProducts)
    {
        return $pivotProducts->transform(function (Product $product) {
            $product->append(['thumb_url', 'link_product', 'brand_name', 'brand_series_name']);
            $product->addHidden(['thumbImage', 'productUrlType', 'brandSeries']);
            return $product;
        });
    }

    private function filterEmptyPackCategory(Collection $pack_categories): Collection
    {
        return $pack_categories
            // filter out empty packs category
            ->filter(function (PackCategory $packCategory) {
                return (bool) $packCategory->packs->count();
            })
            // delete discontinue index
            ->values();
    }

    /**
     * @param Collection $pack_categories
     */
    private function transformPackCategoryProducts(Collection $pack_categories): void
    {
        $pack_categories->each(function (PackCategory $packCategory) {
            // @since v2.3.9 之前 $packCategory 没有分类图片，需要用第一个整妆的图补上默认分类图
            if (! $packCategory->image) {
                $first_pack_thumb = $packCategory->packs[0]->thumb ?? null;
                $packCategory->image = $first_pack_thumb;
            }

            $this->transformPacksAssetsProducts($packCategory->packs);
        });
    }

    /**
     * @param Collection|Pack[] $packs
     */
    private function transformPacksAssetsProducts(Collection $packs): void
    {
        $packs->each(function (Pack $pack) {
            $this->transformPackAssetsProducts($pack);
        });
    }

    /**
     * @param Pack $pack
     */
    private function transformPackAssetsProducts(Pack $pack): void
    {
        $pack->assets->each(function (Asset $asset) use ($pack) {
            $filter_products = PackRepository::filterCachedCustomerPackAssetRelationProducts(
                Guard::deviceAccount()->customer_id, $pack, $asset
            );

            $asset->pivot_products = $this->transformPivotProducts(
//                $asset->getPivotProducts($pack)
                $filter_products
            );
        });
    }

    /**
     * @param Collection|Pack[] $unCategorizedPacks
     *
     * @return array
     */
    private function assembleOtherPackCategory(Collection $unCategorizedPacks): array
    {
        $other_pack_category = [
            'id'    => Pack::PACK_CATEGORY_NULL_ID,
            'name'  => trans('app.other'),
            'packs' => $unCategorizedPacks
        ];

        return $other_pack_category;
    }

    /**
     * @param $customer
     *
     * @return Pack[]|\Illuminate\Database\Eloquent\Builder[]|Collection
     */
    private function getUnCategorizedPacks(Customer $customer)
    {
        $un_categorized_packs = (new Pack)
            ->filterIsDeleted(Pack::IS_NO_DELETED)
            ->where([
                'customer_id'      => $customer->id,
                'pack_category_id' => Pack::PACK_CATEGORY_NULL_ID,
            ])
            ->with('assets')
            ->get();

        $this->transformPacksAssetsProducts($un_categorized_packs);

        return $un_categorized_packs;
    }

    /**
     * @param $pack_categories
     * @param Customer $customer
     */
    private function appendOtherPackCategory(Collection $pack_categories, Customer $customer): void
    {
        $unCategorizedPacks = $this->getUnCategorizedPacks($customer);

        if ($unCategorizedPacks->count()) {
            $pack_categories->push(
                $this->assembleOtherPackCategory($unCategorizedPacks)
            );
        }
    }

    private function queryPackOnShelf(): \Closure
    {
        /**
         * @param HasMany|Pack $builder
         */
        return function (HasMany $builder) {
            $pack = new Pack;

            $builder->filterIsDeleted(Pack::IS_NO_DELETED)
                ->latest($pack->qualifyColumn('priority'))
                ->latest($pack->qualifyColumn('created_at'))
            ;
        };
    }
}
